class CoordsCalc
{
  CoordsCalc()
  {
  }

  void update()
  {
    int currX = vidW;
    int currW = 0;
    boolean[][] matchingPixels = new boolean[vidH][vidW];
    boolean isYAssigned = false;
    boolean isWAssigned = false;
    for (int j = 0; j < coloursAssigned; j++) 
    {
      currX = vidW;
      currW = 0;
      isYAssigned = false;
      isWAssigned = false;
      for (int i = 0; i < numPixels; i++)
      {
        matchingPixels[abs(i / vidW)][i % vidW] = false;
        color currColor = cam.pixels[i];
        currR = (currColor >> 16) & 0xFF;
        currG = (currColor >> 8) & 0xFF;
        currB = currColor & 0xFF;
        if (isColourWithinRange(j))
        {
          matchingPixels[abs(i / vidW)][i % vidW] = true;
          noStroke();
          if (isShowPixels) 
          {
            fill(pixelColours[j]);
            //rect((i % vidW), (abs(i / vidW)), 1, 1); doesn't seem to do anything
            rect((i % vidW) * rectDivide, (abs(i / vidW)) * rectDivide, 1 * rectDivide, 1 * rectDivide);
          }
        }
      }
      setBoundingBox(j, matchingPixels);
      // Find center of bounding box
      centrePoints[j][0] = (squareCoords[j][0] * rectDivide) + ((squareCoords[j][2] * rectDivide) / 2);
      centrePoints[j][1] = (squareCoords[j][1] * rectDivide) + ((squareCoords[j][3] * rectDivide) / 2);
      fill(0, 0, 0);
      ellipse(centrePoints[j][0], centrePoints[j][1], 10, 10);
    }
  }

  boolean isColourWithinRange(int j)
  {
    if (currR > (colourCompareData[j][0] + colourRange) || currR < (colourCompareData[j][0] - colourRange))
    {
      return false;
    }
    if (currG > (colourCompareData[j][1] + colourRange) || currG < (colourCompareData[j][1] - colourRange))
    {
      return false;
    }
    if (currB > (colourCompareData[j][2] + colourRange) || currB < (colourCompareData[j][2] - colourRange))
    {
      return false;
    }
    return true;
  }

  /*
   * Sets the bounding box by finding the inner quartile range of all
   * pixels matching the desired color in the x and y directions, then
   * excludes any outliers from the bounding box (rather than just
   * including any matching pixels).
   */
  private void setBoundingBox(int j, boolean[][] matchingPixels) {
    List<Integer> xCoords = new ArrayList<Integer>();
    List<Integer> yCoords = new ArrayList<Integer>();
    for (int i = 0; i < vidH; i++) {
      for (int k = 0; k < vidW; k++) {
        if (matchingPixels[i][k]) {
          xCoords.add(k);
          yCoords.add(i);
        }
      }
    }
    if (xCoords.size() > 0) {
      Collections.sort(xCoords);
      int xMedian = xCoords.get(xCoords.size() / 2);
      int xLowerQ = xCoords.get((xCoords.size()/ 2) / 2);
      int xUpperQ = xCoords.get(((xCoords.size() - (xCoords.size()/ 2)) / 2) + (xCoords.size()/ 2));
      int xIQR = xUpperQ - xLowerQ;
      Collections.sort(yCoords);
      int yMedian = yCoords.get(yCoords.size() / 2);
      int yLowerQ = yCoords.get((yCoords.size()/ 2) / 2);
      int yUpperQ = yCoords.get(((yCoords.size() - (yCoords.size()/ 2)) / 2) + (yCoords.size()/ 2));
      int yIQR = yUpperQ - yLowerQ;
      squareCoords[j][0] = (int) constrain(xLowerQ - blobOutlierFactor * xIQR, 
                            Collections.min(xCoords), vidW);
      squareCoords[j][1] = (int) constrain(yLowerQ - blobOutlierFactor * yIQR, 
                            Collections.min(yCoords), vidH);
      squareCoords[j][2] = (int) constrain((xUpperQ + blobOutlierFactor * xIQR) - squareCoords[j][0],
                            0, Collections.max(xCoords) - squareCoords[j][0]);
      squareCoords[j][3] = (int) constrain((yUpperQ + blobOutlierFactor * yIQR) - squareCoords[j][1],
                            0, Collections.max(yCoords) - squareCoords[j][1]);
      
    }
  }
}

